
import bpy
import 全局控制.Node.节点和插座基类.bl_UpdateNode as 节点插座查找
import pdb


g_开启节点树更新 = True

def __f_查找要标记要更新的节点(nodes, 可以更新的节点):
	for 当前节点 in nodes:
		子节点s = list( 节点插座查找.f_get子节点(当前节点.outputs).values() )
		#print('子节点s -- == -- ', 子节点s)
		for node in 子节点s:
			可以更新的节点[node.name] = node
			if node.bl_static_type == "GROUP" :
				pass
				#__f_查找要标记要更新的节点(node.node_tree.nodes, 可以更新的节点)
			
		__f_查找要标记要更新的节点(子节点s, 可以更新的节点)
		
def __f_标记要更新的节点(可以更新的节点):
	for key in 可以更新的节点:
		node = 可以更新的节点[key]
		#print('__f_标记要更新的节点 node = ', node, node.type, node.bl_static_type)
		if node.type == 'CUSTOM' or node.bl_static_type == 'GROUP':
			node.f_pushUpdate()





def __f_get一层链接节点(nodes):
	可以更新的节点 = {}
	#回溯更新点 = {}

	for nodeKey in nodes:
		当前节点 = nodes[nodeKey]
		#print('当前节点 = ', 当前节点, 当前节点.f_is未更新())
		是否要更新 = True
		if 当前节点.f_is未更新() or 当前节点.f_is强制Update():
			#以当前插座 查找上一层节点 判断是否以更新
			for 输入插座 in 当前节点.inputs:
				#判断输入插座是否属于无需确认接入插座更新判断
				#print('= 输入插座 = ', 输入插座.node.name, 输入插座.name)
				if 输入插座.node.type == "CUSTOM" and 输入插座.f_is以更新():
					#print('= 输入插座 = ', 输入插座.node.name, 输入插座.name)
					break
				
				上一层节点组 = 节点插座查找.f_from上一层节点(输入插座)
				
				#判断流程控制
				for node in 上一层节点组:
					#if node : print('node A = ', node)
					#if node : print('node B = ', node.type, node)
					#if node and node.type == "CUSTOM" : print('node C = ', node.f_is未更新())
					if node and node.type == "CUSTOM" and node.f_is未更新() and node.f_is强制Update() == False:
						是否要更新 = False
						break
				if 是否要更新 == False :
					break
				
			#print('当前节点.bl_idname = ', 是否要更新, 当前节点.bl_idname, 当前节点.f_is强制Update())
			if 是否要更新 or 当前节点.f_is强制Update():
				#if 当前节点.bl_idname == 'C_SceneNode_循环' :
				#	回溯更新点[当前节点.name] = 当前节点
				#print('A 当前节点.bl_idname = ', 当前节点.bl_idname, 当前节点.name)
				可以更新的节点[当前节点.name] = 当前节点

	return 可以更新的节点#, 回溯更新点
	

def __f_查找下层节点(nodes_map):
	下层节点s = {}
	下层以更新节点s = {}
	#收集顶层节点
	for key in nodes_map:
		n = nodes_map[key]
		是否为顶层节点 = True
		
		nodes = list(节点插座查找.f_get子节点(n.outputs).values())
		#print('__f_查找下层节点 = ', nodes, n)
		for 输出节点 in nodes:
			下层节点s[输出节点.name] = 输出节点
			
	return 下层节点s
	
def f_updateNode(nodes, 空间数据=None):
	可以更新的节点 = __f_get一层链接节点(nodes)
	#print("可以更新的节点 = ", 可以更新的节点)
	不需要更新的节点 = []
	for key in 可以更新的节点:
		node = 可以更新的节点[key]
		
		if node.bl_static_type != 'GROUP' and node.type != 'REROUTE':
			#print("node ------- 可以更新的节点 = ", node, node.bl_static_type, node.inputs[0])
			s = node.inputs['_>']
			if s.is_linked :
				if s.f_getData() == False:
					node.f_标记为已更新()
					节点插座查找.f_设置下层节点为以更新状态(node)
					#print('设置下层节点为以更新状态')
					不需要更新的节点.append(key)
					continue
			#else:
			#	s.f_setData(False)
		#print('是否跳出循环 == ', node.name, node.id_data) 
		是否跳出循环 = node.f_update()
		
		if 是否跳出循环 : return True
		
	for k in 不需要更新的节点:
		可以更新的节点.pop(k)

	下层节点 = __f_查找下层节点(可以更新的节点)
	#print("下层节点 = ", 下层节点)
	if len(下层节点) :
		#for n in 下层节点:
		#	print(' ----------- 下层节点 ', 下层节点[n].name, 下层节点[n].f_is未更新()) 
		return f_updateNode(下层节点, 空间数据)
	return False






def f_get需更新节点(nodes):
	可以更新的节点 = __f_get一层链接节点(nodes)
	可以更新的下层节点 = __f_查找下层节点(可以更新的节点)
	return 可以更新的节点, 可以更新的下层节点

def f_update节点(node):
	if node.bl_static_type != 'GROUP' and node.type != 'REROUTE':
		s = node.inputs['_>']
		if s.is_linked and s.f_getData() == False:
			node.f_标记为已更新()
			节点插座查找.f_设置下层节点为以更新状态(node)
			return
	
	是否跳出循环 = node.f_update()
	if 是否跳出循环 : return True





#顶层节点s[key].f_is以更新() == False or 

def f_标记要更新的节点(顶层节点s):
	可以更新的节点 = {}
	for key in 顶层节点s:
		if 顶层节点s[key].f_is强制Update() :
			__f_查找要标记要更新的节点([顶层节点s[key]], 可以更新的节点)
	__f_标记要更新的节点(可以更新的节点)
	
def f_从顶层开始更新(顶层节点s, 空间数据=None):
	f_标记要更新的节点(顶层节点s)
	return f_updateNode(顶层节点s, 空间数据)

def f_插座顶层节点(nodes):
	顶层节点s = {}
	#收集顶层节点
	for n in nodes:
		是否为顶层节点 = True
		
		名称长度 = len(n.name)
		if (n.type == 'GROUP_OUTPUT' or n.bl_idname == 'C_SceneNode_流程合并' or n.bl_idname == 'C_SceneNode_引用'
			or n.type == 'GROUP_INPUT' ) : 
			是否为顶层节点 = False
		else:
			for 输入节点 in n.inputs:
				if 输入节点.is_linked :
					是否为顶层节点 = False
					break
			#|________|
		
		if 是否为顶层节点 :
			if n.type == 'GROUP_INPUT' :
				'''sanNode = 节点插座查找.f_get子节点(n.outputs)
				for sn in list(sanNode.values()) :
					if sn.m_Type == '引用镜像':
						引用Node = 节点插座查找.f_get子节点(sn.outputs)
						for sn_n1 in list(引用Node.values()) :
							if 节点插座查找.f_node_是否需要更新(sn) :
								顶层节点s[sn_n1.name] = sn_n1

					elif 节点插座查找.f_node_是否需要更新(sn) :
					#for _sn in sn :
						顶层节点s[sn.name] = sn'''
				pass	
			else:
				if 节点插座查找.f_node_是否需要更新(n) :
					顶层节点s[n.name] = n
				#if 是否为顶层节点 and n.type != 'REROUTE' and n.f_is自动Update() and n.m_Type != '引用镜像':
	return 顶层节点s



def f_NT_update(nodes, 空间数据=None):
	顶层节点s = f_插座顶层节点(nodes)
	#print('顶层节点s = ', 顶层节点s)
	#print('nodes = ', n.id_data.name)
	return f_从顶层开始更新(顶层节点s, 空间数据)
	
	#标记要更新的节点
	'''可以更新的节点 = {}
	for key in 顶层节点s: 
		#顶层节点s[key].f_pushUpdate()
		__f_查找要标记要更新的节点([顶层节点s[key]], 可以更新的节点)
	__f_标记要更新的节点(可以更新的节点)
	#print('可以更新的节点 = ', 可以更新的节点)
	return f_updateNode(顶层节点s, 空间数据)'''


